﻿using Nop.Admin.Models.Customers;
using Nop.Admin.Models.Security;
using Nop.Core;
using Nop.Core.Domain.Customers;
using Nop.Services.Customers;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Admin.Controllers
{
	public partial class SecurityController : BaseAdminController
	{
		#region Fields

		private readonly ILogger _logger;
		private readonly IWorkContext _workContext;
		private readonly IPermissionService _permissionService;
		private readonly ICustomerService _customerService;
		private readonly ILocalizationService _localizationService;

		#endregion

		#region Constructors

		public SecurityController(ILogger logger, IWorkContext workContext,
			IPermissionService permissionService,
			ICustomerService customerService,
			ILocalizationService localizationService)
		{
			this._logger = logger;
			this._workContext = workContext;
			this._permissionService = permissionService;
			this._customerService = customerService;
			this._localizationService = localizationService;
		}

		#endregion

		#region Methods

		public virtual ActionResult AccessDenied(string pageUrl)
		{
			var currentCustomer = _workContext.CurrentCustomer;
			if (currentCustomer == null || currentCustomer.IsGuest())
			{
				_logger.Information(string.Format("Access denied to anonymous request on {0}", pageUrl));
				return View();
			}

			_logger.Information(string.Format("Access denied to user #{0} '{1}' on {2}", currentCustomer.Username, currentCustomer.Username, pageUrl));


			return View();
		}

		public virtual ActionResult Permissions()
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageAcl))
				return AccessDeniedView();

			var model = new PermissionMappingModel();

			var permissionRecords = _permissionService.GetAllPermissionRecords();
			// 排除掉不显示的角色
			int[] excludeIds = new[] { _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered).Id, _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Guests).Id };
			var customerRoles = _customerService.GetAllCustomerRoles(showAll: true).Where(m => !excludeIds.Contains(m.Id));
			foreach (var pr in permissionRecords.Where(m => m.ParentId == 0))
			{
				model.AvailablePermissions.Add(new PermissionRecordModel
				{
					Name = pr.Name,
					SystemName = pr.SystemName
				});
				foreach (var prd in permissionRecords.Where(m => m.ParentId == pr.Id))
				{
					model.AvailablePermissions.Add(new PermissionRecordModel
					{
						Name = pr.Name + "-" + prd.Name,
						SystemName = prd.SystemName
					});
				}
			}
			foreach (var cr in customerRoles)
			{
				model.AvailableCustomerRoles.Add(new CustomerRoleModel
				{
					Id = cr.Id,
					Name = cr.Name
				});
			}
			foreach (var pr in permissionRecords)
				foreach (var cr in customerRoles)
				{
					bool allowed = pr.CustomerRoles.Count(x => x.Id == cr.Id) > 0;
					if (!model.Allowed.ContainsKey(pr.SystemName))
						model.Allowed[pr.SystemName] = new Dictionary<int, bool>();
					model.Allowed[pr.SystemName][cr.Id] = allowed;
				}

			return View(model);
		}

		[HttpPost, ActionName("Permissions")]
		public virtual ActionResult PermissionsSave(FormCollection form)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageAcl))
				return AccessDeniedView();

			var permissionRecords = _permissionService.GetAllPermissionRecords();
			// 排除掉不显示的角色
			int[] excludeIds = new[] { _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered).Id, _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Guests).Id };
			var customerRoles = _customerService.GetAllCustomerRoles(showAll: true).Where(m => !excludeIds.Contains(m.Id));

			foreach (var cr in customerRoles)
			{
				string formKey = "allow_" + cr.Id;
				var permissionRecordSystemNamesToRestrict = form[formKey] != null ? form[formKey].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>();

				foreach (var pr in permissionRecords)
				{

					bool allow = permissionRecordSystemNamesToRestrict.Contains(pr.SystemName);
					if (allow)
					{
						if (pr.CustomerRoles.FirstOrDefault(x => x.Id == cr.Id) == null)
						{
							pr.CustomerRoles.Add(cr);
							_permissionService.UpdatePermissionRecord(pr);
						}
					}
					else
					{
						if (pr.CustomerRoles.FirstOrDefault(x => x.Id == cr.Id) != null)
						{
							pr.CustomerRoles.Remove(cr);
							_permissionService.UpdatePermissionRecord(pr);
						}
					}
				}
			}

			SuccessNotification(_localizationService.GetResource("Admin.Configuration.ACL.Updated"));
			return RedirectToAction("Permissions");
		}
		#endregion
	}
}
